<script setup lang="ts">
import { debounce } from '@/utils/debounce'

const {
  modelValue = null, // 绑定值
  apiFn, // apiFn 为一个函数，用于自定义请求
  api, // api 为请求地址， 和 apiFn 二选一
  apiMethod = 'post', // 请求方式
  apiParams, // 请求参数
  labelKey = 'label', // 默认label
  valueKey = 'value', // 默认value
  remote = true, // 是否远程搜索
  searchKey, // 远程搜索的字段
  multiple = false, // 是否多选
  placeholder = "请选择" // placeholder
} = defineProps<{
  modelValue: string | number | (string | number)[] | undefined | null
  apiFn?: (params: any) => Promise<any>
  api?: string
  apiMethod?: 'get' | 'post'
  apiParams?: any
  labelKey?: string
  valueKey?: string
  remote?: boolean // 采用本地搜索还是远程搜索
  searchKey?: string
  multiple?: boolean
  width?: string,
  placeholder?: string
}>()

const emit = defineEmits<{
  'update:modelValue': [string | number | (string | number)[] | undefined]
}>()

const loading = ref(false)

const options = ref<{ label: string; value: string | number }[]>([])

const value = computed({
  get: () => modelValue,
  set: val => {
    emit('update:modelValue', val)
  },
})

const params = ref<any>({
  ...apiParams,
})

const getOptions = () => {
  loading.value = true
  if (apiFn) {
    apiFn(params.value)
      .then((res: any) => {
        options.value = res.data.data.map((item: any) => {
          return {
            label: item[labelKey],
            value: item[valueKey],
          }
        })
      })
      .finally(() => {
        loading.value = false
      })
  } else if (api) {
    const { fetch } = useFetch()
    fetch[apiMethod](api, params.value)
      .then((res: any) => {
        options.value = res.data.data.map((item: any) => ({
          label: item[labelKey],
          value: item[valueKey],
        }))
      })
      .finally(() => {
        loading.value = false
      })
  }
}

const handleSearch = debounce((query: string) => {
  if (searchKey) {
    params.value[searchKey] = query
  }
  getOptions()
}, 500)

onMounted(async () => {
  await getOptions()
})

watch(
  () => apiParams,
  () => {
    // 清空选择值
    value.value = multiple ? [] : undefined
    params.value = { ...apiParams }
    // 通知外部清空modelValue
    getOptions()
  },
  {
    deep: true,
  },
)
</script>
<template>
  <n-select
    v-model:value="value"
    :options="options"
    filterable
    :remote="remote"
    :loading="loading"
    @search="handleSearch"
    :multiple="multiple"
    clearable
    :style="{ width }"
    :placeholder="placeholder"
  ></n-select>
</template>

<style scoped></style>
